package ascloud.auth.config;

import java.util.Collection;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.session.HttpSessionEventPublisher;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@EnableWebSecurity
@EnableMethodSecurity
@Configuration(proxyBeanMethods = false)
public class ResourceServerConfig {

	@Bean
	SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//		http
//				.authorizeRequests()
//				.requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
//				.requestMatchers(HttpMethod.GET, "/user/info", "/api/foos/**")
//				.hasAuthority("SCOPE_springdoc.read")
//				.requestMatchers(HttpMethod.POST, "/api/foos")
//				.hasAuthority("SCOPE_springdoc.write")
//				.anyRequest()
//				.authenticated()
//				.and()
//				.oauth2ResourceServer()
//				.jwt();
		// @formatter:off
		http
			.authorizeHttpRequests(authorize -> authorize
					.requestMatchers("/actuator/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
//					.requestMatchers(HttpMethod.GET, "/user/info", "/api/foos/**").hasAuthority("SCOPE_springdoc.read")
//					.requestMatchers(HttpMethod.POST, "/api/foos").hasAuthority("SCOPE_springdoc.write")
					.anyRequest().authenticated())
			.oauth2ResourceServer(oauth2ResourceServer -> oauth2ResourceServer
					.jwt(Customizer.withDefaults()));
		// @formatter:on
		log.info("securityFilterChain");
		return http.build();
	}

	@Bean
	JwtAuthenticationConverter jwtAuthenticationConverter() {

		JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
		converter.setJwtGrantedAuthoritiesConverter(jwt -> {

			Collection<GrantedAuthority> scope = new JwtGrantedAuthoritiesConverter().convert(jwt);

			JwtGrantedAuthoritiesConverter grantedConverter = new JwtGrantedAuthoritiesConverter();
			grantedConverter.setAuthorityPrefix("");
			grantedConverter.setAuthoritiesClaimName("role");
			Collection<GrantedAuthority> role = grantedConverter.convert(jwt);
//			log.info("role:{}", role);
			scope.addAll(role);

			return scope;
		});
		return converter;
	}

	@Bean
	RoleHierarchy roleHierarchy() {
		return RoleHierarchyImpl.fromHierarchy("ROLE_ADMIN > ROLE_STAFF > ROLE_USER"
				+ System.getProperty("line.separator") + "ROLE_A > ROLE_B > ROLE_C");
	}

	@Bean
	MethodSecurityExpressionHandler methodSecurityExpressionHandler(RoleHierarchy roleHierarchy) {
		DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
		expressionHandler.setRoleHierarchy(roleHierarchy);
		return expressionHandler;
	}

	@Bean
	HttpSessionEventPublisher httpSessionEventPublisher() {
		return new HttpSessionEventPublisher();
	}

}
